/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ecom.dao;

import ecom.entity.Orders;
import ecom.entity.ProductStore;
import ecom.entity.Purchase;
import ecom.entity.Store;
import ecom.exception.DataAccessLayerException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * Classe qui permet de creer un ensemble d'element dans un contexte transactionnel
 * @author simon
 */
public class TransactionnalDAO {
    protected Session session;
    protected Transaction tx;

    public TransactionnalDAO() {
        HibernateFactory.buildIfNeeded();
    }
    
    /**
     * Permet de sauvegarder une commande dans un contexte transactionnel tout ou rien
     * @param order 
     */
    public void createOrderWithTransaction(Orders order, List<ProductStore> productStoreList, Map<Integer, Double> mappingStoreAccount) {
        try {
            startOperation();
            
            // on sauve la commande
            session.saveOrUpdate(order);
            
            // on sauve les achats
            for (Purchase p : order.getPurchaseList()) {
                p.setOrders(order);
                session.save(p);
            }
            
            // on met a jour le client notamment l'account
            session.saveOrUpdate(order.getCustomer().getAccount());
            
            // decremente le stock de chaque produit dans ProductStore
            for (ProductStore prStore : productStoreList) {
                session.saveOrUpdate(prStore);                
            }
            
            
            // On modifie les comptes des magasins impacter
            for(Entry<Integer, Double> entry : mappingStoreAccount.entrySet()) {
                Integer storeId = entry.getKey();
                Double valueToDeposit = entry.getValue();
                
                Store store = (Store) session.load(Store.class, storeId);
                store.getAccount().setBalance(store.getAccount().getBalance() + valueToDeposit);
                session.saveOrUpdate(store); 
            }
            
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    
    
    protected void handleException(HibernateException e) throws DataAccessLayerException {
        HibernateFactory.rollback(tx);
        throw new DataAccessLayerException(e);
    }

    protected void startOperation() throws HibernateException {

        if(session == null || !session.isOpen())
            session = HibernateFactory.openSession();

        if(tx == null || !tx.isActive())
            tx = session.beginTransaction();
    }

    public void closeSession() {
        HibernateFactory.close(session);
    }
    
}
